﻿using ServiceStack.Redis;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ServiceStack.Redis.Generic;
using ServiceStack.Text;
namespace Cylong.Cache
{
    public class RedisService : ICacheProvider, IRedisService
    {
        public RedisService()
        {
        }

        #region 单体


        /// <summary>
        /// 更新缓存
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key">缓存建</param>
        /// <param name="t">缓存值</param> 
        /// <remarks>更新缓存</remarks>
        /// <returns></returns>
        public bool Update<T>(string key, T t)
        {
            try
            {
                using (IRedisClient redisClient = RedisBase.RedisClient())
                {
                    bool b = this.Remove(key);
                    if (b == true)
                    {
                        return redisClient.Set<T>(key, t);
                    }
                    return false;
                }
            }
            catch
            {
                return false;
            }
        }

        /// <summary>
        /// 设置过期缓存
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key">缓存建</param>
        /// <param name="t">缓存值</param> 
        /// <remarks>根据传入的key修改一条记录的值，当key不存在则添加，无过期时间</remarks>
        /// <returns></returns>
        public bool Write<T>(string key, T t)
        {
            try
            {
                using (IRedisClient redisClient = RedisBase.RedisClient())
                {
                    return redisClient.Set<T>(key, t);
                }
            }
            catch
            {
                return false;
            }
        }
        /// <summary>
        /// 设置缓存
        /// </summary>
        /// <typeparam name="T">对象</typeparam>
        /// <param name="key">缓存键</param>
        /// <param name="t">对象</param>
        /// <param name="expireTime">时间(分)</param>
        /// <returns></returns>
        public bool Write<T>(string key, T t, TimeSpan expireTime)
        {
            using (IRedisClient redisClient = RedisBase.RedisClient())
            {
                return redisClient.Set<T>(key, t, expireTime);
            }
        }
        /// <summary>
        /// 获取
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <returns></returns>
        public T Get<T>(string key)
        {
            using (IRedisClient redisClient = RedisBase.RedisClient())
            {
                return redisClient.Get<T>(key);
            }
        }

        public bool Remove(string key)
        {
            using (IRedisClient redisClient = RedisBase.RedisClient())
            {
                return redisClient.Remove(key);
            }
        }

        public T GetOrAdd<T>(string key, Func<string, T> setFunc) where T : class
        {

            T obj = Get<T>(key);
            if (obj == null)
            {
                return setFunc(key);
            }
            else
            {
                Remove(key);
                obj = setFunc(key);
                Write<T>(key, obj);
                return obj;
            }
        }
        #endregion

        #region String
        #endregion

        #region  List
        /// <summary>
        /// 添加一个项到内部的List 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="t"></param>
        public void List_Add<T>(string key, T t)
        {
            using (IRedisClient redisClient = RedisBase.RedisClient())
            {
                var redisTypedClient = redisClient.As<T>();
                redisTypedClient.AddItemToList(redisTypedClient.Lists[key], t);
            }
        }

        /// <summary>
        /// 根据IEnumerable数据添加链表
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="listId"></param>
        /// <param name="values"></param>
        /// <param name="timeout">秒</param>
        public void AddList<T>(string listId, IEnumerable<T> values, int timeout = 0)
        {
            using (IRedisClient redisClient = RedisBase.RedisClient())
            {
                IRedisTypedClient<T> iredisClient = redisClient.As<T>();
                var redisList = iredisClient.Lists[listId];
                redisList.AddRange(values);
            }
        }

        /// <summary>
        /// 根据ListId获取泛型值。
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key">ListID</param>
        /// <returns></returns>
        public List<T> List_GetList<T>(string key)
        {
            try
            {
                using (IRedisClient redisClient = RedisBase.RedisClient())
                {
                    var redisTypedClient = redisClient.As<T>();
                    return redisTypedClient.GetAllItemsFromList(redisTypedClient.Lists[key]);
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 移除指定ListId的内部List<T>中第二个参数值相等的那一项
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="t"></param>
        /// <returns></returns>
        public bool List_Remove<T>(string key, T t)
        {
            using (IRedisClient redisClient = RedisBase.RedisClient())
            {
                var redisTypedClient = redisClient.As<T>();
                return redisTypedClient.RemoveItemFromList(redisTypedClient.Lists[key], t) > 0;
            }
        }
        #endregion

        #region  Hash

        #region 写入
        /// <summary>
        /// 向hashid集合中添加key/value
        /// </summary>       
        public bool SetEntryInHash(string hashid, string key, string value)
        {
            using (IRedisClient redisClient = RedisBase.RedisClient())
            {
                return redisClient.SetEntryInHash(hashid, key, value);
            }
        }

        /// <summary>
        /// 如果hashid集合中存在key/value则不添加返回false，如果不存在在添加key/value,返回true
        /// </summary>
        public bool SetEntryInHashIfNotExists(string hashid, string key, string value)
        {
            using (IRedisClient redisClient = RedisBase.RedisClient())
            {
                return redisClient.SetEntryInHashIfNotExists(hashid, key, value);
            }
        }

        /// <summary>
        /// 存储对象T t到hash集合中
        /// </summary>
        public void StoreAsHash<T>(T t)
        {
            using (IRedisClient redisClient = RedisBase.RedisClient())
            {
                redisClient.StoreAsHash<T>(t);
            }
        }

        /// <summary>
        /// 获取hashid数据集中，key的value数据
        /// </summary>
        public string GetValueFromHash(string hashid, string key)
        {
            using (IRedisClient redisClient = RedisBase.RedisClient())
            {
                return redisClient.GetValueFromHash(hashid, key);
            }
        }

        /// <summary>
        /// 存储数据到hash表
        /// </summary>
        public bool Hash_Set<T>(string hashid, string key, T t)
        {
            using (IRedisClient redisClient = RedisBase.RedisClient())
            {
                string value = ServiceStack.Text.JsonSerializer.SerializeToString<T>(t);
                return redisClient.SetEntryInHash(hashid, key, value);
            }
        }
        #endregion

        /// <summary>
        /// 获取所有hashid数据集的key/value数据集合
        /// </summary>
        public Dictionary<string, string> GetAllEntriesFromHash(string hashid)
        {
            return RedisBase.ClientRedis.GetAllEntriesFromHash(hashid);
        }
        /// <summary>
        /// 获取hashid数据集中的数据总数
        /// </summary>
        public long GetHashCount(string hashid)
        {
            return RedisBase.ClientRedis.GetHashCount(hashid);
        }
        /// <summary>
        /// 判断hashid数据集中是否存在key的数据
        /// </summary>
        public bool Hash_Exist<T>(string hashid, string key)
        {
            return RedisBase.ClientRedis.HashContainsEntry(hashid, key);
        }
        /// <summary>
        /// 删除hashid数据集中的key数据
        /// </summary>
        public bool RemoveEntryFromHash(string hashid, string key)
        {
            return RedisBase.ClientRedis.RemoveEntryFromHash(hashid, key);
        }

        /// <summary>
        /// 获取hashid数据集中，key的value数据
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="hashId"></param>
        /// <param name="key"></param>
        /// <returns></returns>
        public T Hash_Get<T>(string hashId, string key)
        {
            using (IRedisClient redisClient = RedisBase.RedisClient())
            {
                string value = redisClient.GetValueFromHash(hashId, key);
                return ServiceStack.Text.JsonSerializer.DeserializeFromString<T>(value);
            }
        }

        /// <summary>
        /// 获取整个hash的数据
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <returns></returns>
        public List<T> Hash_GetAll<T>(string hashId)
        {
            var list = RedisBase.ClientRedis.GetHashValues(hashId);
            if (list != null && list.Count > 0)
            {
                List<T> result = new List<T>();
                foreach (var item in list)
                {
                    var value = ServiceStack.Text.JsonSerializer.DeserializeFromString<T>(item);
                    result.Add(value);
                }
                return result;
            }
            return null;
        }

        #endregion

        #region  Set
        /// <summary>
        /// 随机获取key集合中的一个值
        /// </summary>
        public string GetRandomItemFromSet(string key)
        {
            return RedisBase.ClientRedis.GetRandomItemFromSet(key);
            //return RedisBase.Core.GetRandomItemFromSet(key);
        }

        public HashSet<string> GetAllItemsFromSet(string key)
        {
            return RedisBase.ClientRedis.GetAllItemsFromSet(key);
        }

        /// <summary>
        /// key集合中添加value值
        /// </summary>
        public void AddItemToSet(string key, string value)
        {
            RedisBase.ClientRedis.AddItemToSet(key, value);
            //RedisBase.Core.AddItemToSet(key, value);
        }

        /// <summary>
        /// Set添加集合
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="t"></param>
        public void Set_Add<T>(string key, T t)
        {
            using (IRedisClient redisClient = RedisBase.RedisClient())
            {
                var redisTypedClient = redisClient.As<T>();
                redisTypedClient.Sets[key].Add(t);
            }
        }
        /// <summary>
        /// 获取所有key集合的值
        /// </summary>
        public T GetRandomItemFromSets<T>(string key)
        {
            using (IRedisClient redisClient = RedisBase.RedisClient())
            {
                var redisTypedClient = redisClient.As<T>();
                return redisTypedClient.GetRandomItemFromSet(redisTypedClient.Sets[key]);
            }
        }

        /// <summary>
        /// Set删除
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        public void Set_Remove<T>(string key)
        {
            using (IRedisClient redisClient = RedisBase.RedisClient())
            {
                var redisTypedClient = redisClient.As<T>();
                redisTypedClient.Sets[key].Clear();
            }
        }

        #endregion

        #region SortedSet
        #endregion



    }
}
